package com.uminho.egendme;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.TypedArray;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SlidingDrawer;
import android.widget.TextView;
import android.widget.Toast;

import com.markupartist.android.widget.ActionBar;
import com.markupartist.android.widget.ActionBar.AbstractAction;
import com.uminho.calendar.AppointmentDialog;
import com.uminho.exceptions.DestroyException;
import com.uminho.exceptions.InvalidOAuthParametersError;
import com.uminho.exceptions.InvalidOAuthTokenError;
import com.uminho.exceptions.NotAllowedError;
import com.uminho.exceptions.OAuthServiceFailureError;
import com.uminho.exceptions.SaveException;
import com.uminho.http.InternalStorage;
import com.uminho.http.Webservice;
import com.uminho.objects.Appointment;
import com.uminho.objects.AppointmentNotification;
import com.uminho.objects.Notification;
import com.uminho.objects.exchangeNotification;
import com.uminho.preferences.PreferencesHandler;
import com.uminho.tools.Disponibilidades;
import com.uminho.tools.NotificationsDef;

public class Dashboard extends Activity {

	SlidingDrawer slidingDrawer;
	Button search, agenda, calendar, favorites, profile, settings, clearNotifications;
	LocationManager locationManager;
	ProgressDialog myProgressDialog = null; 
	Handler messages;
	Double lat, lon, alt;
	ListView notificationList;
	ArrayList<Notification> notifications=null;
	private Notifications mBoundService;
	boolean mIsBound = false;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		PreferencesHandler.initRefreshTime();
		setContentView(R.layout.dashboard);

		final ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
		actionBar.addAction(new NotificationsAction(getNotificationsIcon(0)));

		actionBar.setHomeLogo(R.drawable.logo);
		//actionBar.setHomeAction(new HomeAction(getNotificationsIcon(1)));




		locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

		LocationListener locationListener = new LocationListener() {
			public void onLocationChanged(Location location) {
				lat = location.getLatitude();
				lon = location.getLongitude();
				alt = location.getAltitude();
				Log.d("Location Updated","New Location:"+lat+"--"+lon+"--"+alt);
			}

			public void onStatusChanged(String provider, int status, Bundle extras) {}

			public void onProviderEnabled(String provider) {}

			public void onProviderDisabled(String provider) {}
		};



		// Register the listener with the Location Manager to receive location updates
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5, 0, locationListener);
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5, 0, locationListener);


		//Start the service
		Intent i = new Intent(this, Notifications.class);
		doBindService();
		startService(i);

		// You can also assign the title programmatically by passing a
		// CharSequence or resource id.
		// actionBar.setTitle(R.string.some_title);
		// actionBar.setHomeAction(new IntentAction(this,
		// HomeActivity.createIntent(this), R.drawable.ic_title_home_default));
		// actionBar.addAction(new IntentAction(this, createShareIntent(),
		// R.drawable.ic_title_share_default));
		// actionBar.addAction(new ToastAction());

		slidingDrawer = (SlidingDrawer) findViewById(R.id.SlidingDrawer);
		search = (Button) findViewById(R.id.buttonsearch);
		agenda = (Button) findViewById(R.id.buttonagenda);
		calendar = (Button) findViewById(R.id.buttoncalendar);
		favorites = (Button) findViewById(R.id.buttonfavorites);
		profile = (Button) findViewById(R.id.buttonprofile);
		settings = (Button) findViewById(R.id.buttonsettings);
		clearNotifications = (Button) findViewById(R.id.notificationsclear);
		notificationList = (ListView) findViewById(R.id.notificationsList);

		//myProgressDialog = ProgressDialog.show(this,getString(R.string.loading), getString(R.string.getnotifications), true); 

		getNotifications();

		notificationList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				final int positionF = position;
				if(notifications.get(position).getNotificationType().startsWith("appointment") || notifications.get(position).getNotificationType().startsWith("client_late") ||  notifications.get(position).getNotificationType().startsWith("recurrent_") || notifications.get(position).getNotificationType().startsWith("time_available") ){

					new Thread() {
						@Override
						public void run() {
							Webservice w = Webservice.getInstance();	
							try {								
								Boolean a = w.markAsRead(notifications.get(positionF).getNotificationId());
								Log.d("noti",a.toString());
								getNotifications();												

							} catch (ClientProtocolException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (InvalidOAuthParametersError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (InvalidOAuthTokenError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (OAuthServiceFailureError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (NotAllowedError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (JSONException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (SaveException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (DestroyException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (URISyntaxException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}.start();
					AppointmentNotification app = (AppointmentNotification) notifications.get(position);
					Log.d("appointment info", app.getAppointment().getId()+"");
					AppointmentDialog a = new AppointmentDialog(Dashboard.this,app.getAppointment());
					a.show();			
				}else if (notifications.get(position).getNotificationType().startsWith("exchange")){

					new Thread() {
						@Override
						public void run() {
							Webservice w = Webservice.getInstance();	
							try {								
								Boolean a = w.markAsRead(notifications.get(positionF).getNotificationId());
								Log.d("noti",a.toString());								
								getNotifications();												

							} catch (ClientProtocolException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (InvalidOAuthParametersError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (InvalidOAuthTokenError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (OAuthServiceFailureError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (NotAllowedError e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (JSONException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (SaveException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (DestroyException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (URISyntaxException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}.start();
					exchangeNotification exn = (exchangeNotification) notifications.get(positionF);	
					ExchangeDialog ex;
					if(notifications.get(position).getNotificationType().startsWith("exchange_request")){											
						ex = new ExchangeDialog(Dashboard.this, exn.getResponder_appointment(), exn.getRequester_appointment(), exn.getExchange_id());
					}else{
						ex = new ExchangeDialog(Dashboard.this, exn.getResponder_appointment(), exn.getRequester_appointment(), exn.getExchange_id(), false);
					}
					ex.show();



				}



			}
		});

		messages = new Handler() {

			@Override
			public void handleMessage(Message msg) {

				if(msg.what==-1){
					Toast.makeText(Dashboard.this,getString(R.string.impossiblereachtheserver),Toast.LENGTH_LONG).show();
				}
				else if(msg.what==-10){
					myProgressDialog.dismiss();
					Intent calendaractiv = new Intent(Dashboard.this, Calendar.class);
					startActivityForResult(calendaractiv, 0);
				}
				else if(msg.what==-11){
					//token/auth error
					myProgressDialog.dismiss();
					Toast.makeText(Dashboard.this, getString(R.string.autentication_error), Toast.LENGTH_LONG).show();
					InternalStorage.goLoggin(Dashboard.this);
				}
				else if(msg.what==-12){
					//token/auth error
					myProgressDialog.dismiss();
					Toast.makeText(Dashboard.this, getString(R.string.working_offline), Toast.LENGTH_LONG).show();
				}else if(msg.what==-2){
					notificationList.setAdapter(new ImageAndTextAdapter(Dashboard.this, R.layout.favorites_row, notifications));										
					actionBar.removeActionAt(0);
					actionBar.addAction(new NotificationsAction(getNotificationsIcon(0)));	
				}
				else{
					actionBar.removeActionAt(0);
					actionBar.addAction(new NotificationsAction(getNotificationsIcon(msg.what)));
					notificationList.setAdapter(new ImageAndTextAdapter(Dashboard.this, R.layout.favorites_row, notifications));
				}
				//if(myProgressDialog.isShowing()) myProgressDialog.dismiss();	
			}

		};



		search.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {

				Intent search = new Intent(Dashboard.this,Search.class);
				search.putExtra("lat", lat);
				search.putExtra("lon", lon);
				startActivity(search);


			}});




		clearNotifications.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Log.d("NotSize", ""+notifications.size());
				new Thread() {
					@Override
					public void run() {
						Webservice w = Webservice.getInstance();	
						try {
							for(Notification n : notifications){
								w.markAsRead(n.getNotificationId());
								Log.d("Notification Marked as Read:",""+n.getNotificationId());
								messages.sendEmptyMessage(-2);
							}
							notifications.clear();
							

						} catch (ClientProtocolException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InvalidOAuthParametersError e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InvalidOAuthTokenError e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (OAuthServiceFailureError e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (NotAllowedError e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (SaveException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (DestroyException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (URISyntaxException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}.start();

			}
		});

		agenda.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Intent agendaActivity = new Intent(Dashboard.this, Agenda.class);
				startActivity(agendaActivity);
			}
		});

		calendar.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				myProgressDialog = ProgressDialog.show(Dashboard.this,getString(R.string.loading), getString(R.string.loadingcalendar), true); 
				new Thread() {
					@Override
					public void run() {
						Webservice w = Webservice.getInstance();									
						HashMap<Date, Integer> infoCalendars = new HashMap<Date, Integer>();
						try {
							ArrayList<ArrayList<Appointment>> listoflistofapp=null;
							listoflistofapp = w.getAgenda();
							Log.d("Size", ""+listoflistofapp);

							if(listoflistofapp != null){
								for(ArrayList<Appointment> appoints: listoflistofapp ){
									GregorianCalendar d = appoints.get(0).getStartDate();
									Date date = d.getTime();
									Date newDate=new Date(date.getYear(),date.getMonth(),date.getDate());
									infoCalendars.put(newDate, appoints.size()*100/12);	

								}
								Disponibilidades.busyDays=infoCalendars;
								Disponibilidades.saveBusyDays();
							}
							else throw new Exception();

						} catch (InvalidOAuthParametersError e) {
							messages.sendEmptyMessage(-11);
							e.printStackTrace();
						} catch (InvalidOAuthTokenError e) {
							messages.sendEmptyMessage(-11);
							e.printStackTrace();
						} catch (Exception e) {
							Disponibilidades.openBusyDays();
							messages.sendEmptyMessage(-12);
							e.printStackTrace();
						} 
						messages.sendEmptyMessage(-10);
					}
				}.start();



			}
		});

		favorites.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Intent searchActivity = new Intent(Dashboard.this,
						Favorites.class);
				startActivityForResult(searchActivity, 0);
			}
		});

		profile.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Intent searchActivity = new Intent(Dashboard.this,
						Profile.class);
				startActivity(searchActivity);
			}
		});

		settings.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				Intent settingsActivity = new Intent(Dashboard.this,
						Settings.class);
				//settingsActivity.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
				startActivityForResult(settingsActivity, 0);

			}
		});



	}
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		Log.d("Dashboard", "actvityRequest "+requestCode+" "+resultCode);
		if(resultCode==2){
			Log.d("Dashboard", "finish");
			finish();
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	/****f* Dashboard/loadDisponibilidades
	 * DESCRIPTION
	 * Método executado para carregar o estado da disponibilidades do calendario para memoria
	 * RESULT
	 * Estado das disponibilidades em memoria
	 ****
	 */
	private ArrayList<ArrayList<Appointment>> loadDisponibilidades(){
		ArrayList<ArrayList<Appointment>> listForAgenda=null;
		try {
			FileInputStream fis = openFileInput("agenda");
			if(fis!=null){
				ObjectInputStream ois = new ObjectInputStream(fis);
				listForAgenda = (ArrayList<ArrayList<Appointment>>) ois.readObject();
				ois.close();
				fis.close();}
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
		}
		return listForAgenda;
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.dashboardmenu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.menurefresh) {
			//myProgressDialog = ProgressDialog.show(this,getString(R.string.loading), getString(R.string.getprofile), true);
			getNotifications();
		}
		return true;
	}




	private int getNotificationsIcon(int size){
		int icon = 0;
		switch(size){
		case 0 : icon = R.drawable.ic_action_not0;
		break;
		case 1 : icon = R.drawable.ic_action_not1;
		break;
		case 2 : icon = R.drawable.ic_action_not2;
		break;
		case 3 : icon = R.drawable.ic_action_not3;
		break;
		case 4 : icon = R.drawable.ic_action_not4;
		break;
		case 5 : icon = R.drawable.ic_action_not5;
		break;
		case 6 : icon = R.drawable.ic_action_not6;
		break;
		case 7 : icon = R.drawable.ic_action_not7;
		break;
		case 8 : icon = R.drawable.ic_action_not8;
		break;
		case 9 : icon = R.drawable.ic_action_not9;
		break;
		default: icon = R.drawable.ic_action_notplus;
		}

		return icon;
	}

	private void getNotifications(){
		new Thread() {

			@Override
			public void run() {

				Webservice ser = Webservice.getInstance();

				try {
					notifications = ser.getNotifications();
					Log.d("notifications Size",notifications.size()+"");
					messages.sendEmptyMessage(notifications.size());
				} catch (ClientProtocolException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					messages.sendEmptyMessage(-1);
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvalidOAuthParametersError e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvalidOAuthTokenError e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (OAuthServiceFailureError e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NotAllowedError e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (SaveException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (DestroyException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

		}.start();
	}

	public static Intent createIntent(Context context) {
		Intent i = new Intent(context, Dashboard.class);
		i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		return i;
	}



	private class NotificationsAction extends AbstractAction {

		public NotificationsAction(int iconId) {
			super(iconId);
		}

		public void performAction(View view) {
			slidingDrawer.animateOpen();
		}

	}

	private class HomeAction extends AbstractAction {

		public HomeAction(int iconId) {
			super(iconId);
		}

		public void performAction(View view) {
			slidingDrawer.animateOpen();
		}

	}

	public class ImageAndTextAdapter extends ArrayAdapter<Notification> {

		private LayoutInflater mInflater;

		private ArrayList<Notification> mlistNotifications;
		private TypedArray mIcons;

		private int mViewResourceId;

		public ImageAndTextAdapter(Context ctx, int viewResourceId,
				ArrayList<Notification> listNotifications) {
			super(ctx, viewResourceId, listNotifications);

			mInflater = (LayoutInflater)ctx.getSystemService(
					Context.LAYOUT_INFLATER_SERVICE);

			mlistNotifications = listNotifications;


			mViewResourceId = viewResourceId;
		}

		@Override
		public int getCount() {
			return mlistNotifications.size();
		}

		@Override
		public Notification getItem(int position) {
			return mlistNotifications.get(position);
		}

		@Override
		public long getItemId(int position) {
			return mlistNotifications.get(position).getNotificationId();//fazer isto
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			convertView = mInflater.inflate(mViewResourceId, null);
			Notification n = notifications.get(position);

			ImageView iv = (ImageView)convertView.findViewById(R.id.image);
			iv.setImageDrawable(getResources().getDrawable(NotificationsDef.notificationResourceIdApp(n.getNotificationType())));

			TextView title = (TextView)convertView.findViewById(R.id.favorite_row_title);
			TextView desc = (TextView)convertView.findViewById(R.id.favorite_row_description);

			title.setText(NotificationsDef.notificationStringId(n.getNotificationType())); 
			desc.setText("");

			return convertView;
		}




	}


	private ServiceConnection mConnection = new ServiceConnection() {
		public void onServiceConnected(ComponentName className, IBinder service) {
			// This is called when the connection with the service has been
			// established, giving us the service object we can use to
			// interact with the service.  Because we have bound to a explicit
			// service that we know is running in our own process, we can
			// cast its IBinder to a concrete class and directly access it.
			mBoundService = ((Notifications.LocalBinder)service).getService();

		}

		public void onServiceDisconnected(ComponentName className) {
			// This is called when the connection with the service has been
			// unexpectedly disconnected -- that is, its process crashed.
			// Because it is running in our same process, we should never
			// see this happen.
			mBoundService = null;
		}
	};




	void doBindService() {
		// Establish a connection with the service.  We use an explicit
		// class name because we want a specific service implementation that
		// we know will be running in our own process (and thus won't be
		// supporting component replacement by other applications).
		bindService(new Intent(Dashboard.this, 
				Notifications.class), mConnection, Context.BIND_AUTO_CREATE);
		mIsBound = true;
	}

	void doUnbindService() {
		if (mIsBound) {
			// Detach our existing connection.
			unbindService(mConnection);
			mIsBound = false;
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		doUnbindService();
	}


}


